﻿#include "geometricutility.h"
#include "DblSize.h"
#include "DblPoint.h"
#include "Pline2DHandler.h"
#include "CmdManager.h"
#include "SendPointHandlerBase.h"
#include "Scene.h"
#include "Ucs.h"
#include "Pline2D.h"
#include "Operation/OpAdd.h"
#include "QtOSGWidget.h"

CDblPoint osgPointToCDblPoint(const osg::Vec3d& point);

osg::Vec3d cDblPointToOsgPoint(const CDblPoint& point);

void handleBoundaryCondition(const osg::Vec3d& startPt, const osg::Vec3d& endPt,const CDblSize& direction,double& sweepAng)
{
	double dx = startPt.x() - endPt.x();
	double dy = startPt.y() - endPt.y();
	bool flag = direction.cx*dy + direction.cy*dx > 0.0;
	if (flag)
	{
		sweepAng = std::abs(sweepAng);

	}
	else
	{
		sweepAng = -std::abs(sweepAng);
	}
}

CDblSize CalDirectionFromNode(const PlineNode& node, const CDblPoint& point)
{
	if (node.m_bulge == 0.0)
	{
		return CDblSize(point.x - node.m_point.x(), point.y - node.m_point.y());
	}
	CDblPoint center;
	double radius;
	double startAng;
	double sweepAng;
	CalArcFromSEH(osgPointToCDblPoint(node.m_point), point, node.m_bulge, center,
		radius, startAng, sweepAng);
	double endAng = startAng + sweepAng;
	endAng *= (double)M_PI / 180.0;
	double dx = cos(endAng);
	double dy = sin(endAng);
	if (sweepAng > 0.0)
	{
		return CDblSize(-dy, dx);
	}
	else
	{
		return CDblSize(dy, -dx);
	}
}

Pline2DHandler::Pline2DHandler() :m_Direction(0, 1) 
{
}

Pline2DHandler::~Pline2DHandler()
{
}

void Pline2DHandler::input(const QVariant& data, const QString& rawInput, CommandSource cs)
{
	auto sph = getSendPointHandler();
	auto scene = getScene();
	auto widget3D = getWidget();
	auto ucs = scene->getCurrentUCS();
	if (data.type() == QVariant::Bool && !data.toBool())
	{
		if (m_pline)
		{
			widget3D->pauseRenderThread();
			ucs->removeChild(m_pline);
			widget3D->resumeRenderThread();
		}
		emit finished();
		return;
	}

	if (status() == 0)
	{
		if (sph)
		{
			sph->setPointMask(CS_LBTNDOWN);
		}
		m_pline = std::make_shared<Pline2D>(ucs.get());
		m_pline->setColor(ucs->getUCSColor());
		widget3D->pauseRenderThread();
		ucs->addChild(m_pline);
		widget3D->resumeRenderThread();
		cmdManager()->setPlane((Plane2DKind)ucs->getKind());
		prompt(1, tr("指定起点:"));
		return;
	}

	if (status() == 1)
	{
		if (sph)
		{
			sph->setPointMask(CS_LBTNDOWN | CS_MOUSEMOVE);
		}
		osg::Vec3d ucspt;
		if (getPoint2D(*ucs, data, rawInput, cs, ucspt))
		{
			widget3D->pauseRenderThread();
			m_pline->addNode(ucspt,0.0);
			m_pline->addNode(ucspt,0.0);
			widget3D->resumeRenderThread();
			showRubberLine(true);
			setRubberLineP1(ucspt);
			prompt(2, tr("指定第二点或[圆弧(A)/撤销(U)]:"));
		}
		return;
	}
	//绘制直线
	if (status() == 2)
	{
		osg::Vec3d ucspt;
		int nodeCount = m_pline->getNodeCount();
		std::vector<PlineNode> nodes = m_pline->node();
		if (data.type() == QVariant::Bool && data.toBool())
		{
			nodes.pop_back();
			widget3D->pauseRenderThread();
			m_pline->setNode(nodes);
			widget3D->resumeRenderThread();
			endCommond(scene);
			return;
		}
		if (data.type() == QVariant::String)
		{
			int nodeCount = m_pline->getNodeCount();
			auto command = data.value<QString>();
			if (command == tr("A") || command == tr("a"))
			{
				CDblPoint center;
				double radius, startAng, sweepAngle;
				bool success = CalArcFromSED(osgPointToCDblPoint(nodes[nodeCount - 2].m_point),
					osgPointToCDblPoint(nodes[nodeCount - 1].m_point),
					m_Direction, center, radius, startAng, sweepAngle);
				if (std::abs(std::abs(sweepAngle) - 180) < 1e-5)
				{
					handleBoundaryCondition(nodes[nodeCount - 2].m_point, nodes[nodeCount - 1].m_point,m_Direction,sweepAngle);
				}
				if (success)
				{
					CalSEHFromArc(center, radius, startAng, sweepAngle,
						osgPointToCDblPoint(nodes[nodeCount - 2].m_point),
						osgPointToCDblPoint(nodes[nodeCount - 1].m_point),
						nodes[nodeCount - 2].m_bulge);
					m_pline->setNode(nodes);
				}
				if (nodeCount < 4)
					prompt(3, tr("指定圆弧的终点或[角度(A)/中心(CE)/方向(D)/线段(L)/半径(R)/第二点(S)]/撤销(U)]:"));
				else
					prompt(3, tr("指定圆弧的终点或[角度(A)/中心(CE)/闭合(CL)/方向(D)/线段(L)/半径(R)/第二点(S)/撤销(U)]:"));
			}
			else if (command == tr("U") || command == tr("u"))
			{
				undoPlineSegment();
			}
			else if (command == tr("C") || command == tr("c"))
			{
				if (nodeCount <=3)
				{
					remark(tr("无效的输入"));
				}
				else
				{
					nodes[nodeCount - 1].m_point = nodes[0].m_point;
					m_pline->setNode(nodes);
					endCommond(scene);
				}
			}
			else
			{
				remark(tr("无效的输入"));
			}
		}
		else if (getPoint2D(*ucs, data, rawInput, cs, ucspt))
		{
			nodes[nodeCount - 1].m_point = ucspt;
			if (cs == CS_MOUSEMOVE)
			{
				setRubberLineP2(ucspt);
				widget3D->pauseRenderThread();
				m_pline->setNode(nodes);
				widget3D->resumeRenderThread();
			}
			else
			{
				setRubberLineP1(ucspt);
				m_Direction = CalDirectionFromNode(nodes[nodeCount - 2],
					osgPointToCDblPoint(nodes[nodeCount - 1].m_point));
				widget3D->pauseRenderThread();
				m_pline->setNode(nodes);
				m_pline->addNode(ucspt,0.0);
				widget3D->resumeRenderThread();
				if (nodeCount < 3)
					prompt(2, tr("指定第二点或[圆弧(A)/撤销(U)]:"));
				else
					prompt(2, tr("指定第二点或[圆弧(A)/闭合(C)/撤销(U)]"));
			}
		}
		else
		{
			remark(tr("无效的输入"));
		}
		return;
	}

	//画圆弧
	if (status() == 3)
	{
		osg::Vec3d ucspt;
		int nodeCount = m_pline->getNodeCount();
		std::vector<PlineNode> nodes = m_pline->node();
		if (data.type() == QVariant::Bool && data.toBool())
		{
			nodes.pop_back();
			widget3D->pauseRenderThread();
			m_pline->setNode(nodes);
			widget3D->resumeRenderThread();
			endCommond(scene);
			return;
		}
		
		if (data.type() == QVariant::String)
		{
			auto command = data.value<QString>();
			if (command == tr("L") || command == tr("l"))
			{
				nodes[nodeCount - 2].m_bulge = 0.0;
				widget3D->pauseRenderThread();
				m_pline->setNode(nodes);
				widget3D->resumeRenderThread();
				if (nodeCount < 4)
					prompt(2, tr("指定下一点或[圆弧(A)/撤销(U)]:"));
				else
					prompt(2, tr("指定下一点或[圆弧(A)/闭合(C)/撤销(U)]:"));
				return;
			}
			else if (command == tr("U") || command == tr("u"))
			{
				undoPlineSegment();
			}
			else if (command == tr("CL") || command == tr("cl"))
			{
				if (nodeCount == 2)
					remark(tr("无效的输入"));
				else
				{
					
					PlineNode lastNode = nodes[nodeCount - 2];
					PlineNode firstNode = nodes[0];
					CDblPoint center;
					double radius, startAng, sweepAngle;
					CalArcFromSED(osgPointToCDblPoint(lastNode.m_point), osgPointToCDblPoint(firstNode.m_point),
						m_Direction, center, radius,
						startAng, sweepAngle);
					if (std::abs(std::abs(sweepAngle) - 180) < 1e-5)
					{
						handleBoundaryCondition(lastNode.m_point, firstNode.m_point, m_Direction, sweepAngle);
					}
					CDblPoint start, end;
					CalSEHFromArc(center, radius, startAng, sweepAngle,start,end,nodes[nodeCount - 2].m_bulge);
					nodes[nodeCount - 1].m_point = cDblPointToOsgPoint(end);
					widget3D->pauseRenderThread();
					m_pline->setNode(nodes);
					widget3D->resumeRenderThread();
					endCommond(scene);
				}
			}
			else if (command == tr("A") || command == tr("a"))
			{
				nodes[nodeCount - 2].m_bulge = 0.0;
				nodes[nodeCount - 1].m_point = nodes[nodeCount - 2].m_point;
				widget3D->pauseRenderThread();
				m_pline->setNode(nodes);
				widget3D->resumeRenderThread();
				prompt(4, tr("指定包含角:"));
			}
			else if (command == tr("CE") || command == tr("ce"))
			{
				nodes[nodeCount - 1].m_point =nodes[nodeCount - 2].m_point;
				nodes[nodeCount - 2].m_bulge = 0.0;
				widget3D->pauseRenderThread();
				m_pline->setNode(nodes);
				widget3D->resumeRenderThread();
				prompt(10, tr("指定圆弧的中心:"));
			}
			else if (command == tr("D") || command == tr("d"))
			{
				nodes[nodeCount - 1].m_point = nodes[nodeCount - 2].m_point;
				nodes[nodeCount - 2].m_bulge = 0.0;
				widget3D->pauseRenderThread();
				m_pline->setNode(nodes);
				widget3D->resumeRenderThread();
				prompt(13, tr("指定圆弧起点处的切线方向:"));
			}
			else if (command == tr("R") || command == tr("r"))
			{
				nodes[nodeCount - 1].m_point = nodes[nodeCount - 2].m_point;
				nodes[nodeCount - 2].m_bulge = 0.0;
				widget3D->pauseRenderThread();
				m_pline->setNode(nodes);
				widget3D->resumeRenderThread();
				prompt(15,tr("指定圆弧半径:"));
			}
			else if (command == tr("S") || command == tr("s"))
			{
				nodes[nodeCount - 1].m_point = nodes[nodeCount - 2].m_point;
				nodes[nodeCount - 2].m_bulge = 0.0;
				widget3D->pauseRenderThread();
				m_pline->setNode(nodes);
				widget3D->resumeRenderThread();
				prompt(18, tr("指定圆弧第二点:"));
			}
			else
			{
				remark(tr("无效的输入"));
			}
		}
		else if (getPoint2D(*ucs, data, rawInput, cs, ucspt))
		{
			int nodeCount = m_pline->getNodeCount();
			CDblPoint center;
			double radius, startAng, sweepAngle;
			bool success = CalArcFromSED(osgPointToCDblPoint(nodes[nodeCount-2].m_point),
										 osgPointToCDblPoint(ucspt),
										 m_Direction,center,radius,startAng,sweepAngle);
			if (std::abs(std::abs(sweepAngle) - 180) < 1e-5)
			{
				handleBoundaryCondition(nodes[nodeCount - 2].m_point, ucspt, m_Direction, sweepAngle);
			}
			if (success)
			{
				nodes[nodeCount - 1].m_point = ucspt;
				CalSEHFromArc(center, radius, startAng,sweepAngle, 
							  osgPointToCDblPoint(nodes[nodeCount - 2].m_point), 
							  osgPointToCDblPoint(nodes[nodeCount - 1].m_point),
							  nodes[nodeCount - 2].m_bulge);
			}
			if (cs == CS_MOUSEMOVE)
			{
				setRubberLineP2(ucspt);
				widget3D->pauseRenderThread();
				m_pline->setNode(nodes);
				widget3D->resumeRenderThread();
			}
			else
			{
				if (success)
				{
					setRubberLineP1(ucspt);
					m_Direction = CalDirectionFromNode(nodes[nodeCount - 2], osgPointToCDblPoint(nodes[nodeCount - 1].m_point));
					widget3D->pauseRenderThread();
					m_pline->setNode(nodes);
					m_pline->addNode(ucspt,0.0);
					widget3D->resumeRenderThread();
					prompt(3, tr("指定圆弧的终点或[角度(A)/中心(CE)/闭合(CL)/方向(D)/线段(L)/半径(R)/第二点(S)/撤销(U)]:"));
				}
				else
				{
					remark(tr("无效的输入"));
				}	
			}
		}
		else
		{
			remark(tr("无效的输入"));
		}
		return;
	}

	if (status() == 4)
	{
		osg::Vec3d ucspt;
		if (data.type() == QVariant::Double)
		{
			m_Angle = data.value<double>();
			if (m_Angle<0.0 || m_Angle>360.0)
				remark(tr("无效的角度"));
			else
			{
				prompt(5, tr("指定圆弧的终点或[中心(C)/半径(R)]"));
			}
		}
		else if (getPoint2D(*ucs, data, rawInput, cs, ucspt))
		{	
			setRubberLineP2(ucspt);
			int nodeCount = m_pline->getNodeCount();
			auto nodes = m_pline->node();
			double dx = ucspt.x() - nodes[nodeCount - 1].m_point.x();
			double dy = ucspt.y() - nodes[nodeCount - 1].m_point.y();
			if (cs != CS_MOUSEMOVE)
			{
				if (dy != 0.0 || dx < 0.0)
				{
					m_Angle = atan2(dy, dx) / M_PI * 180.0;
					prompt(5, tr("指定圆弧的终点或[中心(C)/半径(R)]"));
				}
				else
				{
					remark(tr("无效的输入"));
				}
			}	
		}
		else
		{
			remark(tr("无效的输入"));
		}	
		return;
	}

	if (status() == 5)
	{
		osg::Vec3d ucspt;
		int nodeCount = m_pline->getNodeCount();
		auto nodes = m_pline->node();
		if (data.type() == QVariant::String)
		{
			auto command = data.value<QString>();
			if (command == tr("C") || command == tr("c"))
			{
				prompt(6, tr("指定圆弧的中心:"));
			}
			else if (command == tr("R") || command == tr("r"))
			{
				nodes[nodeCount - 1].m_point = nodes[nodeCount - 2].m_point;
				nodes[nodeCount - 2].m_bulge = 0.0;
				widget3D->pauseRenderThread();
				m_pline->setNode(nodes);
				widget3D->resumeRenderThread();
				showRubberLine(false);
				prompt(7, tr("指定圆弧半径:"));
			}
			else
			{
				remark(tr("无效的输入"));
			}
		}
		else if (getPoint2D(*ucs, data, rawInput, cs, ucspt))
		{
			showRubberLine(true);
			CDblPoint center;
			double radius;
			double startAng;
			bool bSuccess = CalArcFromSEA(osgPointToCDblPoint(nodes[nodeCount - 2].m_point),
										  osgPointToCDblPoint(ucspt),m_Angle, center, radius,startAng);
			if (bSuccess)
			{
				CDblPoint start, end;
				nodes[nodeCount - 1].m_point = ucspt;
				CalSEHFromArc(center, radius, startAng,
					m_Angle, start, end,
					nodes[nodeCount - 2].m_bulge);
			}
			if (cs == CS_MOUSEMOVE)
			{
				setRubberLineP2(ucspt);
				widget3D->pauseRenderThread();
				m_pline->setNode(nodes);
				widget3D->resumeRenderThread();
			}
			else
			{
				if (bSuccess)
				{
					setRubberLineP1(ucspt);
					m_Direction = CalDirectionFromNode(nodes[nodeCount - 2], osgPointToCDblPoint(nodes[nodeCount - 1].m_point));
					widget3D->pauseRenderThread();
					m_pline->setNode(nodes);
					m_pline->addNode(ucspt,0.0);
					widget3D->resumeRenderThread();
					prompt(3, tr("指定圆弧的终点或[角度(A)/中心(CE)/闭合(CL)/方向(D)/线段(L)/半径(R)/第二点(S)/撤销(U)]:"));
				}
				else
				{
					remark(tr("无效的输入"));
				}
				
			}
			
		}
		else
		{
			remark(tr("无效的输入"));
		}
		return;
	}

	if (status() == 6)
	{
		int nodeCount = m_pline->getNodeCount();
		auto nodes = m_pline->node();
		osg::Vec3d ucspt;
		if (getPoint2D(*ucs, data, rawInput, cs, ucspt))
		{
			auto lastPoint = nodes[nodeCount - 2].m_point;
			bool success = false;
			if (lastPoint != ucspt)
			{
				success = true;
				double dx = lastPoint.x() - ucspt.x();
				double dy = lastPoint.y() - ucspt.y();
				double startAng = atan2(dy, dx) / M_PI * 180.0;
				double radius = sqrt(dx * dx + dy * dy);
				CDblPoint start;
				CDblPoint end;
				CalSEHFromArc(osgPointToCDblPoint(ucspt), radius, startAng, m_Angle,
					start, end,
					nodes[nodeCount - 2].m_bulge);
				nodes[nodeCount - 1].m_point = cDblPointToOsgPoint(end);
				if (cs == CS_MOUSEMOVE)
				{
					m_pline->setNode(nodes);
					setRubberLineP2(ucspt);
				}
				else
				{
					if (success)
					{
						setRubberLineP1(nodes[nodeCount - 1].m_point);
						m_Direction = CalDirectionFromNode(nodes[nodeCount - 2], end);
						widget3D->pauseRenderThread();
						m_pline->setNode(nodes);
						m_pline->addNode(nodes[nodeCount - 1].m_point, 0.0);
						widget3D->resumeRenderThread();
						prompt(3, tr("指定圆弧的终点或[角度(A)/中心(CE)/闭合(CL)/方向(D)/线段(L)/半径(R)/第二点(S)/撤销(U)]:"));
					}
					else
					{
						remark(tr("无效的输入"));
					}
				}	
			}
			else
			{
				remark(tr("无效的输入"));
			}
		}
		else
		{
			remark(tr("无效的输入"));
		}
		return;
	}

	if (status() == 7)
	{
		auto nodes = m_pline->node();
		int nodeCount = m_pline->getNodeCount();
		osg::Vec3d ucspt;
		if (data.type() == QVariant::Double)
		{
			m_Radius = data.value<double>();
			if (m_Radius > 0)
			{
				showRubberLine(true);
				setRubberLineP1(nodes[nodeCount-2].m_point);
				prompt(9, tr("指定圆弧弦的方向:"));
			}
			else
			{
				remark(tr("半径必须大于0"));
			}
		}
		else if (getPoint2D(*ucs, data, rawInput, cs, ucspt))
		{
			if (cs != CS_MOUSEMOVE)
			{
				m_Start = osgPointToCDblPoint(ucspt);
				showRubberLine(true);
				setRubberLineP1(ucspt);
				prompt(8, tr("指定第二点"));
			}
		}
		else
		{
			remark(tr("无效的输入"));
		}
		return;
	}

	if (status() == 8)
	{
		int nodeCount = m_pline->getNodeCount();
		auto nodes = m_pline->node();
		osg::Vec3d ucspt;
		if (getPoint2D(*ucs, data, rawInput, cs, ucspt))
		{
			m_Second = osgPointToCDblPoint(ucspt);
			if (cs == CS_MOUSEMOVE)
			{
				setRubberLineP2(ucspt);
			}
			else
			{
				double dx = m_Second.x - m_Start.x;
				double dy = m_Second.y - m_Start.y;
				if (dx != 0.0 || dy != 0.0)
				{
					m_Radius = sqrt(dx*dx + dy * dy);
					setRubberLineP1(nodes[nodeCount-2].m_point);
					prompt(9,tr("指定圆弧弦的方向"));
				}
				else
				{
					remark(tr("输入数据必须为正"));
				}
			}
		}
		else
		{
			remark(tr("无效的输入"));
		}
		return;
	}

	if (status() == 9)
	{
		int nodeCount = m_pline->getNodeCount();
		auto nodes = m_pline->node();
		osg::Vec3d ucspt;
		if (data.type() == QVariant::Double)
		{
			double dir = data.value<double>()/180*M_PI;
			m_Direction.cx = cos(dir);
			m_Direction.cy = sin(dir);
			CalPlineSegmentFromSARD();
			setRubberLineP1(nodes[nodeCount-2].m_point);
			m_Direction = CalDirectionFromNode(nodes[nodeCount - 2],
				osgPointToCDblPoint(nodes[nodeCount - 1].m_point));
			widget3D->pauseRenderThread();
			m_pline->addNode(nodes[nodeCount - 1].m_point, 0.0);
			widget3D->resumeRenderThread();
			prompt(3, tr("指定圆弧的终点或[角度(A)/中心(CE)/闭合(CL)/方向(D)/线段(L)/半径(R)/第二点(S)/撤销(U)]:"));
		}
		else if (getPoint2D(*ucs, data, rawInput, cs, ucspt))
		{
			m_Direction.cx = ucspt.x() - nodes[nodeCount - 2].m_point.x();
			m_Direction.cy = ucspt.y() - nodes[nodeCount - 2].m_point.y();
			CalPlineSegmentFromSARD();
			if (cs == CS_MOUSEMOVE)
			{
				setRubberLineP2(ucspt);
			}
			else
			{
				setRubberLineP1(nodes[nodeCount - 1].m_point);
				m_Direction = CalDirectionFromNode(nodes[nodeCount - 2],
					osgPointToCDblPoint(nodes[nodeCount - 1].m_point));
				widget3D->pauseRenderThread();
				m_pline->addNode(nodes[nodeCount - 1].m_point,0.0);
				widget3D->resumeRenderThread();
				prompt(3, tr("指定圆弧的终点或[角度(A)/中心(CE)/闭合(CL)/方向(D)/线段(L)/半径(R)/第二点(S)/撤销(U)]:"));
			}
		}
		else
		{
			remark(tr("无效的输入"));
		}
		return;
	}

	if (status() == 10)
	{
		int nodeCount = m_pline->getNodeCount();
		auto nodes = m_pline->node();
		osg::Vec3d ucspt;
		if (getPoint2D(*ucs, data, rawInput, cs, ucspt))
		{
			if (cs == CS_MOUSEMOVE)
			{
				setRubberLineP2(ucspt);
			}
			else
			{
				auto lastPoint = nodes[nodeCount - 1].m_point;
				if (lastPoint != ucspt)
				{
					m_Center = osgPointToCDblPoint(ucspt);
					CDblSize startDirection = osgPointToCDblPoint(nodes[nodeCount - 2].m_point) - m_Center; 
					m_Start.x = atan2(startDirection.cy, startDirection.cx) / M_PI * 180.0;
					m_Radius = sqrt(startDirection.cx*startDirection.cx + startDirection.cy*startDirection.cy);
					setRubberLineP1(ucspt);
					prompt(11, tr("指定圆弧的终点或[角度(A)]"));
				}
				else
				{
					remark(tr("无效的输入"));
				}
			}
		}
		else
		{
			remark(tr("无效的输入"));
		}
		return;
	}

	if (status() == 11)
	{
		int nodeCount = m_pline->getNodeCount();
		auto nodes = m_pline->node();
		osg::Vec3d ucspt;
		if (data.type() == QVariant::String)
		{ 
			auto command = data.value<QString>();
			if (command == tr("A") || command == tr("a"))
			{
				prompt(12, tr("指定包含角"));
			}
		}
		else if (getPoint2D(*ucs, data, rawInput, cs, ucspt))
		{
			CDblPoint end = osgPointToCDblPoint(ucspt);
			bool bSuccess = false;
			if (!osgPointToCDblPoint(nodes[nodeCount - 2].m_point).equal(end) && (!m_Center.equal(end)))
			{
				bSuccess = true;
				CDblPoint center;
				double radius;
				double startAng;
				double sweepAng;
				CalArcFromSCE(osgPointToCDblPoint(nodes[nodeCount - 2].m_point),m_Center, end, radius, startAng,sweepAng);
				CDblPoint startPt;
				CDblPoint endPt;
				CalSEHFromArc(m_Center, radius, startAng,sweepAng, startPt, endPt,nodes[nodeCount - 2].m_bulge);
				nodes[nodeCount - 1].m_point = cDblPointToOsgPoint(endPt);
				widget3D->pauseRenderThread();
				m_pline->setNode(nodes);
				widget3D->resumeRenderThread();
			}
			if (cs ==CS_MOUSEMOVE)
			{
				setRubberLineP2(ucspt);
			}
			else
			{
				if (bSuccess)
				{
					setRubberLineP1(nodes[nodeCount - 1].m_point);
					m_Direction = CalDirectionFromNode(nodes[nodeCount - 2],osgPointToCDblPoint(nodes[nodeCount - 1].m_point));
					widget3D->pauseRenderThread();
					m_pline->setNode(nodes);
					m_pline->addNode(nodes[nodeCount-1].m_point, 0.0);
					widget3D->resumeRenderThread();
					prompt(3, tr("指定圆弧的终点或[角度(A)/中心(CE)/闭合(CL)/方向(D)/线段(L)/半径(R)/第二点(S)/撤销(U)]:"));
				}
				else
				{
					remark(tr("圆弧的起点、终点和中心不能重合"));
				}
			}
		}
		else
		{
			remark(tr("无效的输入"));
		}
		return;
	}

	if (status() == 12)
	{
		int nodeCount = m_pline->getNodeCount();
		auto nodes = m_pline->node();
		osg::Vec3d ucspt;
		if (data.type() == QVariant::Double)
		{
			m_Angle = data.value<double>();
			if (0.0 < m_Angle&&m_Angle < 360.0)
			{
				CDblPoint start;
				CDblPoint end;
				CalSEHFromArc(m_Center, m_Radius, m_Start.x,m_Angle, start, end,nodes[nodeCount - 2].m_bulge);
				nodes[nodeCount - 1].m_point = cDblPointToOsgPoint(end);
				setRubberLineP1(nodes[nodeCount - 1].m_point);
				m_Direction = CalDirectionFromNode(nodes[nodeCount - 2],end);
				widget3D->pauseRenderThread();
				m_pline->setNode(nodes);
				m_pline->addNode(nodes[nodeCount - 1].m_point,0.0);
				widget3D->resumeRenderThread();
				prompt(3, tr("指定圆弧的终点或[角度(A)/中心(CE)/闭合(CL)/方向(D)/线段(L)/半径(R)/第二点(S)/撤销(U)]:"));
			}
			else
			{
				remark(tr("无效的角度"));
			}
		}
		else if (getPoint2D(*ucs, data, rawInput, cs, ucspt))
		{
			bool bSuccess = false;
			double dx = ucspt.x() - nodes[nodeCount - 1].m_point.x();
			double dy = ucspt.y() - nodes[nodeCount - 1].m_point.y();
			if (dy != 0.0 || dx < 0.0)
			{
				bSuccess = true;
				//update segment realtimely
				m_Angle = atan2(dy, dx) / M_PI * 180.0;
				if (m_Angle < 0.0)
					m_Angle += 360.0;
				CDblPoint start;
				CDblPoint end;
				CalSEHFromArc(m_Center, m_Radius,m_Start.x, m_Angle,start, end,nodes[nodeCount - 2].m_bulge);
				nodes[nodeCount - 1].m_point = cDblPointToOsgPoint(end);
				widget3D->pauseRenderThread();
				m_pline->setNode(nodes);
				widget3D->resumeRenderThread();
			}
			if (cs == CS_MOUSEMOVE)
			{
				setRubberLineP2(ucspt);
			}
			else
			{
				if (bSuccess)
				{
					setRubberLineP1(ucspt);
					m_Direction = CalDirectionFromNode(nodes[nodeCount - 2], osgPointToCDblPoint(nodes[nodeCount - 1].m_point));
					widget3D->pauseRenderThread();
					m_pline->setNode(nodes);
					m_pline->addNode(ucspt, 0.0);
					widget3D->resumeRenderThread();
					prompt(3, tr("指定圆弧的终点或[角度(A)/中心(CE)/闭合(CL)/方向(D)/线段(L)/半径(R)/第二点(S)/撤销(U)]:"));
				}
				else
				{
					remark(tr("无效的输入"));
				}
				
			}
		}
		else
		{
			remark(tr("无效的输入"));
		}
		return;
	}

	if (status() == 13)
	{
		int nodeCount = m_pline->getNodeCount();
		auto nodes = m_pline->node();
		osg::Vec3d ucspt;
		if (data.type() == QVariant::Double)
		{
			double dir = data.value<double>() / 180 * M_PI;
			m_Direction.cx = cos(dir);
			m_Direction.cy = sin(dir);
			prompt(14,tr("指定圆弧终点"));
		}
		else if (getPoint2D(*ucs, data, rawInput, cs, ucspt))
		{
			if (cs == CS_MOUSEMOVE)
			{
				setRubberLineP2(ucspt);
			}
			else
			{
				double dx = ucspt.x() - nodes[nodeCount - 1].m_point.x();
				double dy = ucspt.y() - nodes[nodeCount - 1].m_point.y();
				if (dx != 0.0 || dy != 0.0)
				{
					m_Direction.cx = dx;
					m_Direction.cy = dy;
					prompt(14, tr("指定圆弧终点"));
				}
				else
				{
					remark(tr("无效的输入"));
				}
			}
		}
		else
		{
			remark(tr("无效的输入"));
		}
		return;
	}

	if (status() == 14)
	{
		int nodeCount = m_pline->getNodeCount();
		auto nodes = m_pline->node();
		osg::Vec3d ucspt;
		if (getPoint2D(*ucs, data, rawInput, cs, ucspt))
		{
			nodes[nodeCount - 1].m_point = ucspt;
			CDblPoint center;
			double radius, startAng, sweepAngle;
			bool success = CalArcFromSED(osgPointToCDblPoint(nodes[nodeCount - 2].m_point),
				osgPointToCDblPoint(nodes[nodeCount - 1].m_point),
				m_Direction, center, radius, startAng, sweepAngle);
			if (std::abs(std::abs(sweepAngle) - 180) < 1e-5)
			{
				handleBoundaryCondition(nodes[nodeCount - 2].m_point, nodes[nodeCount - 1].m_point, m_Direction, sweepAngle);
			}
			if (success)
			{
				CalSEHFromArc(center, radius, startAng, sweepAngle,
					osgPointToCDblPoint(nodes[nodeCount - 2].m_point),
					osgPointToCDblPoint(nodes[nodeCount - 1].m_point),
					nodes[nodeCount - 2].m_bulge);
			}
			if (cs == CS_MOUSEMOVE)
			{
				widget3D->pauseRenderThread();
				m_pline->setNode(nodes);
				widget3D->resumeRenderThread();
				setRubberLineP2(ucspt);
			}
			else
			{
				if (success)
				{
					setRubberLineP1(ucspt);
					m_Direction = CalDirectionFromNode(nodes[nodeCount - 2], osgPointToCDblPoint(nodes[nodeCount - 1].m_point));
					widget3D->pauseRenderThread();
					m_pline->setNode(nodes);
					m_pline->addNode(ucspt,0.0);
					widget3D->resumeRenderThread();
					prompt(3, tr("指定圆弧的终点或[角度(A)/中心(CE)/闭合(CL)/方向(D)/线段(L)/半径(R)/第二点(S)/撤销(U)]:"));
				}
				else
				{
					remark(tr("无效的输入"));
				}
			}

		}
		else
		{
			remark(tr("无效的输入"));
		}
		return;
	}

	if (status() == 15)
	{
		int nodeCount = m_pline->getNodeCount();
		auto nodes = m_pline->node();
		osg::Vec3d ucspt;
		if (data.type() == QVariant::Double)
		{
			m_Radius = data.value<double>();
			if (m_Radius > 0.0)
			{
				prompt(17, tr("指定圆弧的终点"));
			}
			else
			{
				remark(tr("半径必须为正值"));
			}
		}
		else
		{
			if (getPoint2D(*ucs, data, rawInput, cs, ucspt))
			{
				if (cs != CS_MOUSEMOVE)
				{
					setRubberLineP1(ucspt);
					m_Start = osgPointToCDblPoint(ucspt);
					prompt(16, tr("指定第二个点"));
				}
			}
			else
			{
				remark(tr("无效的输入"));
			}
		}
		return;
	}

	if (status() == 16)
	{
		int nodeCount = m_pline->getNodeCount();
		auto nodes = m_pline->node();
		osg::Vec3d ucspt;
		if (getPoint2D(*ucs, data, rawInput, cs, ucspt))
		{
			if (cs == CS_MOUSEMOVE)
			{
				setRubberLineP2(ucspt);
			}
			else
			{
				double dx = ucspt.x() - m_Start.x;
				double dy = ucspt.y() - m_Start.y;
				if (dx != 0.0 || dy != 0.0)
				{
					m_Radius = sqrt(dx*dx + dy * dy);
					setRubberLineP1(nodes[nodeCount-2].m_point);
					prompt(17, tr("指定圆弧的终点"));
				}
				else
				{
					setRubberLineP1(cDblPointToOsgPoint(m_Start));
					remark(tr("半径必须为正值"));
				}
			}
		}
		else
		{
			remark(tr("无效的输入"));
		}
		return;
	}

	if (status() == 17)
	{
		int nodeCount = m_pline->getNodeCount();
		auto nodes = m_pline->node();
		osg::Vec3d ucspt;
		if (getPoint2D(*ucs, data, rawInput, cs, ucspt))
		{
			CDblPoint center;
			double startAng, sweepAngle;
			bool success = CalArcFromSER(osgPointToCDblPoint(nodes[nodeCount-2].m_point),
										 osgPointToCDblPoint(ucspt),m_Radius,center,startAng,sweepAngle);
			if (success)
			{
				nodes[nodeCount - 1].m_point = ucspt;
				CDblPoint start, end;
				CalSEHFromArc(center, m_Radius, startAng,
					sweepAngle, start, end,
					nodes[nodeCount - 2].m_bulge);
			}
			if (cs == CS_MOUSEMOVE)
			{
				setRubberLineP2(ucspt);
				widget3D->pauseRenderThread();
				m_pline->setNode(nodes);
				widget3D->resumeRenderThread();
			}
			else
			{
				if (success)
				{
					setRubberLineP1(ucspt);
					m_Direction = CalDirectionFromNode(nodes[nodeCount - 2],osgPointToCDblPoint(nodes[nodeCount - 1].m_point));
					widget3D->pauseRenderThread();
					m_pline->setNode(nodes);
					m_pline->addNode(ucspt, 0.0);
					widget3D->resumeRenderThread();
					prompt(3, tr("指定圆弧的终点或[角度(A)/中心(CE)/闭合(CL)/方向(D)/线段(L)/半径(R)/第二点(S)/撤销(U)]:"));
				}
				else
				{
					remark(tr("无效的输入"));
				}
			}
		}
		else
		{
			remark(tr("无效的输入"));
		}
		return;
	}

	if (status() == 18)
	{
		int nodeCount = m_pline->getNodeCount();
		auto nodes = m_pline->node();
		osg::Vec3d ucspt;
		if (getPoint2D(*ucs, data, rawInput, cs, ucspt))
		{
			if (cs == CS_MOUSEMOVE)
			{
				setRubberLineP2(ucspt);
			}
			else
			{
				setRubberLineP1(ucspt);
				m_Second = osgPointToCDblPoint(ucspt);
				prompt(19, tr("指定圆弧终点"));
			}
		}
		else
		{
			remark(tr("无效的输入"));
		}
		return;
	}

	if (status() == 19)
	{
		int nodeCount = m_pline->getNodeCount();
		auto nodes = m_pline->node();
		osg::Vec3d ucspt;
		if (getPoint2D(*ucs, data, rawInput, cs, ucspt))
		{
			CDblPoint center;
			double  radius,startAng, sweepAngle;
			bool success = CalArcFrom3P_SSD(osgPointToCDblPoint(nodes[nodeCount-2].m_point),m_Second,
											osgPointToCDblPoint(ucspt),center,radius,startAng,sweepAngle);
			if (success)
			{
				nodes[nodeCount - 1].m_point = ucspt;
				CDblPoint start, end;
				CalSEHFromArc(center, radius, startAng,sweepAngle, start, end,nodes[nodeCount - 2].m_bulge);
			}
			if (cs == CS_MOUSEMOVE)
			{
				setRubberLineP2(ucspt);
				widget3D->pauseRenderThread();
				m_pline->setNode(nodes);
				widget3D->resumeRenderThread();
			}
			else
			{
				if (success)
				{
					setRubberLineP1(ucspt);
					m_Direction = CalDirectionFromNode(nodes[nodeCount - 2],osgPointToCDblPoint(nodes[nodeCount-1].m_point));
					widget3D->pauseRenderThread();
					m_pline->setNode(nodes);
					m_pline->addNode(ucspt,0.0);
					widget3D->resumeRenderThread();
					prompt(3, tr("指定圆弧的终点或[角度(A)/中心(CE)/闭合(CL)/方向(D)/线段(L)/半径(R)/第二点(S)/撤销(U)]:"));
				}
				else
				{
					remark(tr("无效的输入"));
				}
			}
		}
		else
		{
			remark(tr("无效的输入"));
		}
		return;
	}
}


bool Pline2DHandler::CalPlineSegmentFromSARD()
{
	int nodeCount = m_pline->getNodeCount();
	assert(nodeCount > 1);
	double radius = m_Radius;
	double sweepAng = m_Angle;
	CDblPoint center;
	double startAng;
	std::vector<PlineNode> nodes = m_pline->node();
	bool bSuccess = CalArcFromSARD(osgPointToCDblPoint(nodes[nodeCount - 2].m_point),
		sweepAng, radius, m_Direction,
		center, startAng);
	if (bSuccess)
	{
		CDblPoint start;
		CDblPoint end;
		CalSEHFromArc(center, radius, startAng,
			sweepAng, start,
			end,
			nodes[nodeCount - 2].m_bulge);
		nodes[nodeCount - 1].m_point = cDblPointToOsgPoint(end);
		auto widget3D = getWidget();
		widget3D->pauseRenderThread();
		m_pline->setNode(nodes);
		widget3D->resumeRenderThread();
	}
	return bSuccess != false;
}

void Pline2DHandler::undoPlineSegment()
{
	int nodeCount = m_pline->getNodeCount();
	std::vector<PlineNode> nodes = m_pline->node();
	if (nodeCount > 2)
	{
		setRubberLineP1(nodes[nodeCount-3].m_point);
		nodes.erase(nodes.begin() + nodeCount - 1);
		nodes[nodeCount - 2].m_point = nodes[nodeCount - 3].m_point;
		if (nodeCount == 3)
		{
			nodes[0].m_bulge = 0.0;
			prompt(2, tr("指定第二点或[圆弧(A)/撤销(U)]:"));
		}
		else
		{
			m_Direction = CalDirectionFromNode(nodes[nodeCount-4],osgPointToCDblPoint(nodes[nodeCount-3].m_point));
			if (nodes[nodeCount-3].m_bulge == 0.0)
			{
				prompt(2, tr("指定第二点或 [圆弧(A)/闭合(C)/撤销(U)]"));
			}
			else
			{
				nodes[nodeCount - 3].m_bulge = 0.0;
				prompt(3, tr("指定圆弧的终点或[角度(A)/中心(CE)/闭合(CL)/方向(D)/线段(L)/半径(R)/第二点(S)/撤销(U)]:"));
			}
		}
	}
	else
	{
		nodes[0].m_bulge = 0.0;
		remark(tr("所有段都被撤销"));
		prompt(2, tr("指定第二点或 [圆弧(A)/撤销(U)]"));
	}
	auto widget3D = getWidget();
	widget3D->pauseRenderThread();
	m_pline->setNode(nodes);
	widget3D->resumeRenderThread();
}

void Pline2DHandler::endCommond(Scene* scene)
{
	auto nodes = m_pline->node();
	int nodeCount = m_pline->getNodeCount();
	auto widget3D = getWidget();
	widget3D->pauseRenderThread();
	if (nodeCount < 2)
	{
		auto ucs = scene->getCurrentUCS();
		ucs->removeChild(m_pline);
	}
	m_pline->setNode(nodes);
	widget3D->resumeRenderThread();
	auto undoStack = scene->undoStack();
	std::set<std::shared_ptr<INode>> children;
	children.insert(m_pline);
	undoStack->push(new OpAdd(children));
	emit finished();
	return;
}
